package service

import (
	"awesomeProject/app/model"
	"awesomeProject/app/request"
	"awesomeProject/app/response"
	"awesomeProject/global"
	"awesomeProject/util"
	"context"
	"github.com/fatih/structs"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
	"strconv"
	//"encoding/json"
)

type PurchaseSrv struct{}

func (r *PurchaseSrv) Pagination(req request.PurchasePagination) response.Resp {
	var purchase []model.Purchase
	filter := bson.D{}
	if req.OrderSn != "" {
		filter = append(filter, bson.E{Key: "orderSn", Value: req.OrderSn})
	}
	if req.SkuId != "" {
		skuId, _ := strconv.Atoi(req.SkuId)
		filter = append(filter, bson.E{Key: "skuId", Value: skuId})
	}
	if req.ItemId != "" {
		itemId, _ := strconv.Atoi(req.ItemId)
		filter = append(filter, bson.E{Key: "itemId", Value: itemId})
	}
	//global.LoggerOut(req.ItemId)
	match := bson.D{{"$match", filter}}
	sort := bson.D{{"$sort", bson.M{"isDefault": -1, "sort": 1}}}
	cursor, err := global.MongoDB.Collection(model.Purchase{}.TableName()).Aggregate(context.TODO(), mongo.Pipeline{match, sort})
	if err = cursor.All(context.TODO(), &purchase); err != nil {
		return response.ErrQuery.SetMsg(err.Error())
	}
	if len(purchase) == 0 {
		return response.OK.WithData(map[string]interface{}{
			"total": 0,
			"list":  purchase,
		})
	}

	count := bson.D{{"$count", "total"}}
	countCursor, err := global.MongoDB.Collection(model.Purchase{}.TableName()).Aggregate(context.TODO(), mongo.Pipeline{match, count})
	if err != nil {
		return response.ErrQuery.SetMsg(err.Error())
	}
	var countResult []map[string]interface{}
	if err = countCursor.All(context.TODO(), &countResult); err != nil {
		return response.ErrQuery.SetMsg(err.Error())
	}

	return response.OK.WithData(map[string]interface{}{
		"total": countResult[0]["total"],
		"list":  purchase,
	})
}

func (r *PurchaseSrv) FindBy(id string, field string) (error, model.Purchase) {
	var purchase model.Purchase
	var err error
	//v_id := util.ConvertToInt(id)
	//v_field := util.ConvertToString(field)

	//global.LoggerOut(id)
	var v_id interface{}
	if util.IsNumeric(id) {
		tid, err := strconv.Atoi(id)
		if err == nil {
			v_id = uint(tid)
		}
	} else {
		v_id = id
	}
	v_field := field

	if v_field == "" {
		v_field = "id"
	}
	//global.LoggerOut(v_id)
	//global.LoggerOut(v_field)

	//filter := bson.D{{"id", id}}
	filter := bson.D{}
	if v_field == "_id" {
		////t := bson.NewObjectId(v_id.(string))
		//t := primitive.NewObjectID()
		t, _ := primitive.ObjectIDFromHex(v_id.(string))
		//filter = append(filter, bson.E{Key: v_field, Value: t})
		filter = bson.D{{"_id", t}}
	} else {
		filter = append(filter, bson.E{Key: v_field, Value: v_id})
	}

	if(model.Purchase{}.DbType() == "mongodb") {
		err = global.MongoDB.Collection(model.Purchase{}.TableName()).FindOne(context.TODO(), filter).Decode(&purchase)
	} else {
		err = global.Gorm.Where("id = ?", id).First(&purchase).Error
	}
	return err, purchase
}

func (r *PurchaseSrv) FindByID(id uint) (error, model.Purchase) {
	field := "id"
	return r.FindBy(strconv.Itoa(int(id)), field)
}

func (r *PurchaseSrv) Update(id uint, purchaseUpdate model.Purchase) response.Resp {
	err, purchase := r.FindByID(id)
	if err != nil {
		return response.ErrQuery.SetMsg(err.Error())
	}
	if purchase.ID == 0 {
		return response.ErrRecordNotFound
	}
	purchaseUpdate.ID = purchase.ID
	purchaseUpdate.CreateAt = purchase.CreateAt
	//global.LoggerOut(purchaseUpdate)
	//t, _ := json.Marshal(purchaseUpdate)
	//global.LoggerOut(string(t))
	//t2, _ := json.Marshal(purchase)
	//global.LoggerOut(string(t2))

	if(model.Purchase{}.DbType() == "mongodb") {
		filter := bson.D{{"id", purchase.ID}}
		update := bson.D{{"$set", purchaseUpdate}}
		opts := options.Update().SetUpsert(true)  //如果匹配不存在，则插入

		_, err := global.MongoDB.Collection(model.Purchase{}.TableName()).UpdateOne(context.TODO(), filter, update, opts)
		if err != nil {
			return response.ErrStore.SetMsg(err.Error())
		}
		//将其他的采购信息的是否默认值更新为0
		if purchaseUpdate.IsDefault == 1 {
			err = r._changeOtherNotDefault(purchaseUpdate.ID)
			if err != nil {
				return response.ErrStore.SetMsg(err.Error())
			}
		}
	} else {
		updates := structs.Map(purchaseUpdate)
		if err = global.Gorm.Model(&purchase).Updates(updates).Error; err != nil {
			return response.ErrStore.SetMsg(err.Error())
		}
	}

	return response.OK
}

func (r *PurchaseSrv) Create(purchase model.Purchase) response.Resp {
	if(model.Purchase{}.DbType() == "mongodb") {
		//var purchaseHexID model.PurchaseHexID
		//purchaseHexID.HexID = primitive.NewObjectID()
		purchase.ID = util.GetTableDataID(model.Purchase{}.TableName())
		global.LoggerOut(purchase.ID)

		res, err := global.MongoDB.Collection(model.Purchase{}.TableName()).InsertOne(context.TODO(), purchase)
		if err != nil {
			return response.ErrStore.SetMsg(err.Error())
		}
		InsertedID := res.InsertedID
		global.LoggerOut(InsertedID)

		if InsertedID != nil {
			if oid, ok := InsertedID.(primitive.ObjectID); ok {
				sid := oid.Hex()
				if sid != "" {
					//global.LoggerOut(sid)
					_, r2 := r.FindBy(sid, "_id")
					//global.LoggerOut(r2)
					//global.LoggerOut(r2.ID)
					if r2.ID > 0 {
						id := r2.ID
						//将其他的采购信息的是否默认值更新为0
						if purchase.IsDefault == 1 {
							err = r._changeOtherNotDefault(id)
							if err != nil {
								return response.ErrStore.SetMsg(err.Error())
							}
						}
					}
				}
			}
		}


	} else {
		if err := global.Gorm.Model(&model.Purchase{}).Create(&purchase).Error; err != nil {
			return response.ErrCreate.SetMsg(err.Error())
		}
	}

	return response.OK
}

func (r *PurchaseSrv) Del(id uint) response.Resp {
	err, purchase := r.FindByID(id)
	if err != nil {
		return response.ErrQuery.SetMsg(err.Error())
	}
	if purchase.ID == 0 {
		return response.ErrRecordNotFound
	}
	// 数据删除
	if(model.Purchase{}.DbType() == "mongodb") {
		filter := bson.D{{"id", purchase.ID}}
		_, err := global.MongoDB.Collection(model.Purchase{}.TableName()).DeleteOne(context.TODO(), filter)
		if err != nil {
			return response.ErrStore.SetMsg(err.Error())
		}
	} else {
		if err := global.Gorm.Unscoped().Delete(&purchase).Error; err != nil {
			return response.ErrDel.SetMsg(err.Error())
		}
	}
	return response.OK
}

//将其他的采购信息的是否默认值更新为0
func (r *PurchaseSrv) _changeOtherNotDefault(id uint) (err error) {
	err, purchase := r.FindByID(id)
	if err != nil {
		return err
	}
	//将其他的采购信息的是否默认值更新为0
	purchaseIsDefault := model.PurchaseIsDefault {
		IsDefault: 0,
	}
	purchaseIsDefault.IsDefault = 0

	filter := bson.D{{"id", bson.M{"$ne": purchase.ID}}}
	update := bson.D{{"$set", purchaseIsDefault}}

	if purchase.OrderSn != "" {
		filter = append(filter, bson.E{Key: "orderSn", Value: purchase.OrderSn})
	}
	if purchase.SkuID > 0 {
		filter = append(filter, bson.E{Key: "skuId", Value: purchase.SkuID})
	}
	if purchase.ItemID > 0 {
		filter = append(filter, bson.E{Key: "itemId", Value: purchase.ItemID})
	}

	_, err = global.MongoDB.Collection(model.Purchase{}.TableName()).UpdateMany(context.TODO(), filter, update)
	return err
}

func (r *PurchaseSrv) ChangeIsDefault(id uint, isDefault int) response.Resp {
	err, purchase := r.FindByID(id)
	if err != nil {
		return response.ErrQuery.SetMsg(err.Error())
	}
	if purchase.ID == 0 {
		return response.ErrRecordNotFound
	}
	purchaseIsDefault := model.PurchaseIsDefault {
		IsDefault: isDefault,
	}
	//t, _ := json.Marshal(purchaseIsDefault)
	//global.LoggerOut(string(t))

	if(model.Purchase{}.DbType() == "mongodb") {
		filter := bson.D{{"id", purchase.ID}}
		update := bson.D{{"$set", purchaseIsDefault}}

		_, err := global.MongoDB.Collection(model.Purchase{}.TableName()).UpdateOne(context.TODO(), filter, update)
		if err != nil {
			return response.ErrStore.SetMsg(err.Error())
		}

		//global.LoggerOut(isDefault)
		if isDefault == 1 {
			err = r._changeOtherNotDefault(purchase.ID)
			if err != nil {
				return response.ErrStore.SetMsg(err.Error())
			}
		}
	} else {
		updates := structs.Map(purchaseIsDefault)
		if err = global.Gorm.Model(&purchase).Updates(updates).Error; err != nil {
			return response.ErrStore.SetMsg(err.Error())
		}
	}
	return response.OK
}

func (r *PurchaseSrv) All() response.Resp {
	var purchase []model.Purchase
	if(model.Purchase{}.DbType() == "mongodb") {
		filter := bson.D{}
		match := bson.D{{"$match", filter}}
		sort := bson.D{{"$sort", bson.M{"isDefault": -1, "sort": 1, "id": -1}}}
		cursor, err := global.MongoDB.Collection("purchase").Aggregate(context.TODO(), mongo.Pipeline{match, sort})
		if err = cursor.All(context.TODO(), &purchase); err != nil {
			return response.ErrQuery.SetMsg(err.Error())
		}
	}
	return response.OK.WithData(purchase)
}